<?php

namespace App\V3\V3_2_7\Services;

use App\Services\CommonService;
use App\Services\MessageService;
use App\V3\V3_2_7\Models\HcMaterielTypeModel;
use App\V3\V3_2_7\Models\LogInStorageModel;
use App\V3\V3_2_7\Models\LogOutStorageModel;
use App\V3\V3_2_7\Models\MaterielAnimalInfoModel;
use App\V3\V3_2_7\Models\MaterielClassModel;
use App\V3\V3_2_7\Models\MaterielProductContentModel;
use App\V3\V3_2_7\Models\MaterielsTypeModel;
use App\V3\V3_2_7\Models\MaterielTypeModel;
use App\V3\V3_2_7\Models\SellGoodsDetailModel;
use App\V3\V3_2_7\Models\SellModel;
use App\V3\V3_2_7\Models\SerialNumberModel;
use App\V3\V3_2_7\Models\StorageBatchModel;
use App\V3\V3_2_7\Models\StorageManageModel;
use App\V3\V3_2_7\Models\StorageModel;
use App\V3\V3_2_7\Models\StorageShelfLocationModel;
use App\V3\V3_2_7\Models\StorageShelfModel;
use App\V3\V3_2_7\Models\UpdGoodsCostModel;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Milon\Barcode\DNS1D;
use OSS\Core\OssException;
use OSS\OssClient;
use App\V3\V3_2_7\Models\AdminModel;
use App\V3\V3_2_7\Models\AuditImagesModel;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Storage;

class MaterielTypeService
{

    /**
     * 新建商品信息
     * @param $data
     * AUTHOR  : Sun Wu
     * DateTime: 2022/3/4 15:43
     * @return array
     */
    static public function add($data, $time, $isUseShelf)
    {
        DB::beginTransaction();
        try {
            unset($data['price_type']);
            $shelfId = $data['shelf_id'] ?? '';
            $locationId = $data['location_id'] ?? '';
            $addType = $data['add_type'] ?? '';
            $storageId = $data['storage_id'] ?? '';
            $batchTitle = $data['batch_title'];
            $userId = $data['user_id'];
            $labelId = $data['label_id'];
            $inStorageTime = $data['in_storage_time'];
            $inStorageNum = !empty($data['in_storage_num']) ? $data['in_storage_num'] : 0;

//            if(empty($data['serial_info'])) {
            $serialInfo = $data['serial_info'] ?? [];
//            }

            $labelName = $data['label_name'];
            unset($data['storage_id']);
            unset($data['in_storage_time']);
            unset($data['product_content']);
            unset($data['label_name']);
            unset($data['in_storage_num']);
            unset($data['batch_title']);
            unset($data['user_id']);
            unset($data['add_type']);
            unset($data['shelf_id']);
            unset($data['location_id']);
            unset($data['label_id']);

            if (!empty($data['materiel_img'])) {
                $materielImg = $data['materiel_img'];
                $materielImgGroup = array_filter(explode(',', $data['materiel_img']), function ($v) {
                    return $v !== '';
                });
                $goodsImg = '';
                if (!empty($materielImgGroup[0])) {
                    $goodsImg = $materielImgGroup[0];
                } elseif (empty($materielImgGroup[0]) && !empty($materielImgGroup[1])) {
                    $goodsImg = $materielImgGroup[1];
                }
                $data['materiel_img'] = $goodsImg;
                $data['materiel_thumbnail_img'] = empty($data['materiel_img']) ? '' : $data['materiel_img'] . config('app.aliyun_oss_thumbnail_url');
                $data['materiel_img_group'] = $materielImg;
            }
            $goodsData = $data;
            unset($goodsData['serial_info']);
            unset($goodsData['animal_info']);
            $materielTypeId = MaterielsTypeModel::insertGetId($goodsData);
            $result = ['code' => 0, 'msg' => 'success', 'data' => ['id' => $materielTypeId]];

            if ($addType) {
                $data['storage_id'] = $storageId;
                $data['batch_title'] = $batchTitle;
                $data['user_id'] = $userId;
                $data['in_storage_time'] = $inStorageTime;
                $data['in_storage_num'] = $inStorageNum;
                $data['serial_info'] = $serialInfo;
                $data['shelf_id'] = $shelfId;
                $data['location_id'] = $locationId;
                $data['label_name'] = $labelName;
                $data['label_id'] = $labelId;
                self::createStorageManageInfo(0, $materielTypeId, $data, $time);
            }
            if (!empty($data['animal_info'])) {
                $animalInfo = json_decode($data['animal_info'], true);
                $animalArr['created_at'] = time();
                $animalInfo['main_id'] = $data['main_id'];
                $animalInfo['materiel_type_id'] = $materielTypeId;
                MaterielAnimalInfoModel::query()->insert($animalInfo);
            }
            DB::commit();
            return $result;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::debug('新建商品-普通商品异常:' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    /**
     * 校验物料商品编号是否存在
     * @param $data
     * AUTHOR  : Sun Wu
     * DateTime: 2022/3/4 15:35
     * @return bool
     */
    static public function checkNo($data)
    {
        $checkMaterielNo = MaterielsTypeModel::checkMaterielTypeRandCode($data);

        if (!empty($checkMaterielNo)) {
            return false;
        } else {
            return true;
        }
    }

    static public function checkRandNo($data)
    {
        $checkMaterielNo = MaterielsTypeModel::checkMaterielTypeCode($data);

        if (!empty($checkMaterielNo)) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 验证商品信息是否已存在
     * @param $data
     * AUTHOR  : Sun Wu
     * DateTime: 2022/3/4 15:41
     * @return bool
     */
    static public function checkMaterielInfo($data)
    {
        $checkMaterielInfo = MaterielsTypeModel::checkMaterielInfo($data);
        if (!empty($checkMaterielInfo)) {
            return false;
        } else {
            return true;
        }
    }

    //根据id检索商品信息是否已存在
    static public function checkMateriel($mainId, $id)
    {
        if (empty(MaterielsTypeModel::where(['id' => $id, 'main_id' => $mainId])->first())) {
            return false;
        } else {
            return true;
        }
    }

    //检查除自身外是否有相同的商品信息
    static public function checkMaterielInfoExceptself($data)
    {
        $checkMaterielTypeInfo = MaterielsTypeModel::where([
            'main_id' => $data['main_id'],
            'materiel_name' => $data['materiel_name'],
            'type_name' => $data['type_name'],
            'materiel_no' => $data['materiel_no'],
            'materiel_class_id' => $data['materiel_class_id'],
            'delete_flag' => 0,
        ])
            ->where('id', '!=', $data['id'])
            ->first();

        if (!empty($checkMaterielTypeInfo)) {
            return false;
        } else {
            return true;
        }
    }

    //获取指定商品详细信息
    static public function info($id)
    {
        $info = MaterielTypeModel::info($id);
        if (empty((int)$info['length'])) $info['length'] = "";
        if (empty((int)$info['width'])) $info['width'] = "";
        if (empty((int)$info['height'])) $info['height'] = "";
        if (empty((int)$info['weight'])) $info['weight'] = "";
        if (empty((int)$info['price_last'])) $info['price_last'] = "";
        if (empty((int)$info['lower_selling_price'])) $info['lower_selling_price'] = "";
        $info['spec_img'] = !empty($info['spec_img']) ? explode(',', $info['spec_img']) : [];
        $info['materiel_img_group'] = !empty($info['materiel_img_group']) ? explode(',', $info['materiel_img_group']) : [];
        if (!empty($info['materiel_img'])) {
            if (strpos($info['materiel_img'], ',') !== false) {
                $img = explode(',', $info['materiel_img']);
                if (!empty($img[0])) {
                    $info['materiel_img'] = $img[0];
                } else {
                    $info['materiel_img'] = $img[1];
                }
            }
        }
        $info['materiel_img'] = $info['materiel_img'] ?? '';
        $info['cost_log_list'] = UpdGoodsCostModel::query()
            ->select(
                'created_at',
                'upd_cost as cost'
            )->where([
                'main_id' => $info['main_id'],
                'goods_id' => $info['id']
            ])->limit(5)
            ->orderBy('id', 'desc')
            ->get()->toArray();
        return $info;
    }

    //物料列表
    static public function materielTypeSelect($mainId, $keyword, $condition, $pageSize, $currentPage, $isProductMateriel, $data = [])
    {
        $info = MaterielsTypeModel::materielTypeSelect($mainId, $keyword, $condition, $pageSize, $currentPage, $isProductMateriel, $data);
        foreach ($info as &$value) {
            if (!empty($value['materiel_img'])) {
                $materielImg = array_filter(explode(',', $value['materiel_img']), function ($v) {
                    return $v !== '';
                });
                $value['materiel_img'] = $materielImg[0];
            }


            if ($value['is_product_materiel']) {
                $value['content_type_id'] = MaterielProductContentModel::where([
                    'product_id' => $value['id']
                ])
                    ->pluck('type_id')->toArray();
            } else {
                $value['content_type_id'] = [];
            }
        }

        return $info;
    }

//物料列表
    static public function selectGoodsList($mainId, $keyword, $condition, $pageSize, $currentPage, $isProductMateriel, $data = [])
    {
        $list = MaterielsTypeModel::selectGoodsList($mainId, $keyword, $condition, $pageSize, $currentPage, $isProductMateriel, $data);
        if (!empty($list['data'])) {
            $goodsData = $list['data'];
            foreach ($goodsData as &$val) {
                $query = MaterielsTypeModel::query()->select(
                    'a.id',
                    'materiel_name',
                    'type_name',
                    'materiel_img',
                    'materiel_no',
                    'materiel_class_id',
                    'b.class_name as sec_class_name',
                    'c.id as fir_class_id',
                    'c.class_name as fir_class_name',
                    'a.remark',
                    'a.length',
                    'a.width',
                    'a.height',
                    'a.weight',
                    'a.attribute',
                    'a.cost',
                    'a.selling_price',
                    'a.is_use_serial',
                    'a.materiel_unit',
                    'a.lower_selling_price',
                    'a.is_product_materiel',
                    'a.goods_client_name',
                    'a.goods_supplier_name'
                )
                    ->from('materiel_type as a')
                    ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                    ->leftJoin('materiel_class as c', 'b.parent_id', '=', 'c.id')
                    ->where($condition);
                if (isset($isProductMateriel)) {
                    $query->where('a.is_product_materiel', $isProductMateriel);
                }
                if (!empty($data['f_class_id'])) {
                    $secClassId = MaterielClassModel::query()
                        ->where([
                            'delete_flag' => 0,
                            'main_id' => $mainId,
                            'parent_id' => $data['f_class_id']
                        ])->pluck('id');
                    if (!empty($secClassId->toArray())) {
                        $secClassId = $secClassId->toArray();
                        $query->whereIn('a.materiel_class_id', $secClassId);
                    }
                }
                $val['goods_list'] = $query->where(function ($query) use ($keyword) {
                    if (!empty($keyword)) {
                        $query->orWhere('a.materiel_name', 'like', '%' . $keyword . '%');
                        $query->orWhere('a.type_name', 'like', '%' . $keyword . '%');
                        $query->orWhere('a.materiel_no', 'like', '%' . $keyword . '%');
                    }
                })
                    ->where([
                        'a.delete_flag'=> 0,
                        'b.delete_flag'=> 0,
                        'c.delete_flag'=> 0,
                    ])->where('a.main_id', $mainId)
                    ->where('a.materiel_name',$val['materiel_name'])
                    ->orderBy('a.id', 'DESC')->get();
            }
            $list['data'] = $goodsData;

        }
        return $list;
    }

    //物料列表-含库存信息

    static public function list($user, $data, $storageIdArr = [])
    {
        $condition = [];
        if (!empty($data['materiel_class_id'])) {
            $condition['a.materiel_class_id'] = ['EQ' => $data['materiel_class_id']];
        }

        if (isset($data['is_product_class'])) {
            $condition['c.is_product_class'] = ['EQ' => $data['is_product_class']];
        }

        if (isset($data['is_product_materiel'])) {
            $condition['b.is_product_materiel'] = ['EQ' => $data['is_product_materiel']];
        }

        $keyword = empty($data['keyword']) ? '' : $data['keyword'];


        $typeId = [];
        if (!empty($data['type_id'])) {
            $typeId = array_filter(explode(',', $data['type_id']));
        }

        $info = MaterielsTypeModel::getMaterielTypeList($user, $condition, $keyword, $data, $typeId);
        if (!empty($info)) {
            foreach ($info as $key => &$iVal) {
                if (!empty($value['materiel_img'])) {
                    $materielImg = array_filter(explode(',', $value['materiel_img']), function ($v) {
                        return $v !== '';
                    });
                    $value['materiel_img'] = $materielImg[0];
                }
                if (!empty($storageIdArr)) {
                    if (!in_array($iVal['storage_id'], $storageIdArr)) {
                        unset($info[$key]);
                    }
                }
            }
        }
        $currentPage = $data['currentPage'];
        $result = array_slice(array_values($info), --$data['currentPage'] * $data['pageSize'], $data['pageSize']);

        return [
            'total' => count($info),
            'current_page' => $currentPage,
            'next_page_url' => count($result) < $data['pageSize'] ? null : config('app.url') . "storage_manage_list?=" . ($data['currentPage'] + 1),
            'prev_page_url' => $currentPage == 1 ? null : config('app.url') . "storage_manage_list?=" . ($currentPage - 1),
            "path" => config('app.url') . "storage_manage_list",
            "to" => $currentPage * $data['pageSize'],
            'data' => $result,
            "per_page" => $data['pageSize']
        ];

        return array_values($info);
    }


    //物料列表-含库存信息

    public static function chooseGoodsList($user, $data, $storageIdArr = [])
    {
        $condFarm = [
            'materiel_class_id', 'is_product_class',
            'is_product_materiel', 'keyword', 'storage_id'
        ];
        $result = MaterielsTypeModel::query()
            ->select('a.*')
            ->from('materiel_type as a')
            ->leftJoin('storage_manage as b', 'b.type_id', '=', 'a.id')
            ->leftJoin('storage as e', 'b.storage_id', '=', 'e.id')
            ->where([
                'a.delete_flag' => 0,
                'b.delete_flag' => 0,
                'e.delete_flag' => 0,
                ['in_storage_num', '>', 0]
            ])
            ->where(function ($query) use ($data, $condFarm, $storageIdArr) {
                foreach ($condFarm as $val) {
                    if (!empty($data[$val])) {
                        if ($val === 'keyword') {
                            $query->orWhere('a.materiel_name', 'like', '%' . $data[$val] . '%');
                            $query->orWhere('a.type_name', 'like', '%' . $data[$val] . '%');
                            $query->orWhere('a.materiel_no', 'like', '%' . $data[$val] . '%');
                        } else {
                            if ($val === 'storage_id') {
                                $query->where('b.' . $val, $data[$val]);
                            } else {
                                $query->where('a.' . $val, $data[$val]);
                            }
                        }
                    }
                }
                if (!empty($data['f_class_id'])) {
                    $secClassId = MaterielClassModel::query()
                        ->where([
                            'delete_flag' => 0,
                            'main_id' => $data['main_id'],
                            'parent_id' => $data['f_class_id']
                        ])->pluck('id');
                    if (!empty($secClassId->toArray())) {
                        $secClassId = $secClassId->toArray();
                        $query->whereIn('a.materiel_class_id', $secClassId);
                    }
                }

                if (!empty($data['type_id'])) {
                    $typeId = array_filter(explode(',', $data['type_id']));
                    $query->whereIn('a.id', $typeId);
                }
                if (!empty($storageIdArr))
                    $query->whereIn('b.storage_id', $storageIdArr);
            })->where($user)->groupBy('a.materiel_name')
            ->paginate($data['pageSize'], ['*'], '', $data['currentPage'])->toArray();
        if (!empty($result['data'])) {
            $goodsList = $result['data'];
            foreach ($goodsList as &$val) {
                if (!empty($val['materiel_img'])) {
                    $materielImg = array_filter(explode(',', $val['materiel_img']), function ($v) {
                        return $v !== '';
                    });
                    $val['materiel_img'] = $materielImg[0];
                }
                $val['manage_list'] = StorageManageModel::query()->select(
                    'b.*',
                    'c.id as s_class_id',
                    'c.class_name as s_class_name',
                    'c.class_no as s_class_no',
                    'd.class_name as f_class_name',
                    'd.class_no as f_class_no',
                    'd.id as f_class_id',
                    'a.in_storage_num',
                    'a.storage_id',
                    'e.storage_name',
                    'b.length',
                    'b.width',
                    'b.height',
                    'b.weight',
                    'b.attribute',
                    'b.cost',
                    'a.shelf_id',
                    'a.location_id',
                    's.shelf_name',
                    'l.location_name',
                    'product_use_tag',
                    'a.id as storage_manage_id'
                )
                    ->from('storage_manage as a')
                    ->leftJoin('materiel_type AS b', 'b.id', '=', 'a.type_id')
                    ->leftJoin('materiel_class AS c', 'c.id', '=', 'b.materiel_class_id')
                    ->leftJoin('materiel_class AS d', 'd.id', '=', 'c.parent_id')
                    ->leftJoin('storage as e', 'e.id', '=', 'a.storage_id')
                    ->leftJoin('storage_shelf as s', 'a.shelf_id', '=', 's.id')
                    ->leftJoin('storage_shelf_location as l', 'a.location_id', '=', 'l.id')
                    ->where($user)
                    ->where('a.delete_flag', 0)
                    ->where('b.delete_flag', 0)
                    ->where('e.delete_flag', 0)
                    ->where('c.delete_flag', 0)
                    ->where('d.delete_flag', 0)
                    ->where('b.materiel_name', $val['materiel_name'])
                    ->where([
                        'a.delete_flag' => 0,
                        'b.delete_flag' => 0,
                        'e.delete_flag' => 0,
                        'c.delete_flag' => 0,
                        'd.delete_flag' => 0,
                        ['in_storage_num', '>', 0],
                        'b.materiel_name' => $val['materiel_name']
                    ])
                    ->where(function ($query) use ($data, $condFarm, $storageIdArr) {
                        foreach ($condFarm as $val) {
                            if (!empty($data[$val])) {
                                if ($val === 'keyword') {
                                    $query->orWhere('a.materiel_name', 'like', '%' . $data[$val] . '%');
                                    $query->orWhere('a.type_name', 'like', '%' . $data[$val] . '%');
                                    $query->orWhere('a.materiel_no', 'like', '%' . $data[$val] . '%');
                                } else {
                                    if ($val === 'storage_id') {
                                        $query->where('a.' . $val, $data[$val]);
                                    } else {
                                        $query->where('b.' . $val, $data[$val]);
                                    }
                                }
                            }
                        }
                        if (!empty($data['f_class_id'])) {

                            $secClassId = MaterielClassModel::query()
                                ->where([
                                    'delete_flag' => 0,
                                    'main_id' => $data['main_id'],
                                    'parent_id' => $data['f_class_id']
                                ])->pluck('id');
                            if (!empty($secClassId->toArray())) {
                                $secClassId = $secClassId->toArray();
                                $query->whereIn('b.materiel_class_id', $secClassId);
                            }
                        }
                        if (!empty($data['type_id'])) {
                            $typeId = array_filter(explode(',', $data['type_id']));
                            $query->whereIn('b.id', $typeId);
                        }
                        if (!empty($storageIdArr))
                            $query->whereIn('a.storage_id', $storageIdArr);
                    })->get()->toArray();
            }
            $result['data'] = $goodsList;
        }

        return $result;
    }

    //修改成本价
    static public function editMaterielCost($data)
    {
        DB::beginTransaction();

        try {
            MaterielsTypeModel::where('id', $data['id'])->update(['cost' => $data['cost']]);
            StorageManageModel::where('type_id', $data['id'])->update(['materiel_mean_cost' => $data['cost']]);
            UpdGoodsCostModel::query()->insert([
                'main_id' => $data['main_id'],
                'user_id' => $data['user_id'],
                'goods_id' => $data['id'],
                'upd_cost' => $data['cost'],
            ]);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('修改成本异常:' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    //新建套件
    public static function addProductMateriel(array $data, $time, $isUseShelf)
    {
        $classInfo = MaterielClassModel::getProductClassInfo($data);

        if (empty($classInfo)) {
            return ['code' => 1, 'msg' => '商品类型与套件不匹配，请重试', 'data' => ''];
        }

        $productContent = [];
        if (!empty($data['product_content'])) {
            $productContent = json_decode($data['product_content'], true);
        }

        DB::beginTransaction();

        try {
            $addType = $data['add_type'] ?? '';
            $priceType = $data['price_type'];

//            if(!empty($data['storage_id'])) {
            $storageId = $data['storage_id'] ?? '';
//            }
            $batchTitle = $data['batch_title'];
            $labelName = $data['label_name'];
            $userId = $data['user_id'];
            $labelId = $data['label_id'];
            $inStorageTime = $data['in_storage_time'];
            $inStorageNum = !empty($data['in_storage_num']) ? $data['in_storage_num'] : 0;
//            if(!empty($data['serial_info'])) {
            $serialInfo = $data['serial_info'] ?? [];
//            }

//            if(!empty($data['shelf_id'])) {
            $shelfId = $data['shelf_id'] ?? '';
//            }
//
//            if(!empty($data['location_id'])) {
            $locationId = $data['location_id'] ?? '';
//            }

            unset($data['price_type']);
            unset($data['in_storage_time']);
            unset($data['label_name']);
            unset($data['product_content']);
            unset($data['product_content']);
            unset($data['in_storage_num']);
            unset($data['batch_title']);
            unset($data['user_id']);
            unset($data['storage_id']);
            unset($data['add_type']);
            unset($data['shelf_id']);
            unset($data['location_id']);
            unset($data['label_id']);

            if (!empty($data['materiel_img'])) {
                $materielImg = $data['materiel_img'];
                $materielImgGroup = array_filter(explode(',', $data['materiel_img']), function ($v) {
                    return $v !== '';
                });
                $goodsImg = '';
                if (!empty($materielImgGroup[0])) {
                    $goodsImg = $materielImgGroup[0];
                } elseif (empty($materielImgGroup[0]) && !empty($materielImgGroup[1])) {
                    $goodsImg = $materielImgGroup[1];
                }
                $data['materiel_img'] = $goodsImg;
                $data['materiel_thumbnail_img'] = empty($data['materiel_img']) ? '' : $data['materiel_img'] . config('app.aliyun_oss_thumbnail_url');
                $data['materiel_img_group'] = $materielImg;
            }
            $goodsData = $data;
            unset($goodsData['animal_info']);
            unset($goodsData['serial_info']);
            $materielTypeId = MaterielsTypeModel::insertGetId($goodsData);
            if (!empty($productContent)) {
                $arr = [];
                $sellPrice = 0;//原商品售价
                $price = 0;//改价后金额
                $hasSerialMateriel = 0;
                foreach ($productContent as $value) {
                    if (!isset($value['type_id']) || empty($value['type_id'])) {
                        throw new Exception('请选择要添加的商品');
                    }

                    $materielTypeInfo = MaterielsTypeModel::info($value['type_id']);

                    if (empty($materielTypeInfo)) {
                        throw new Exception('商品信息不存在,请重新套餐组件后添加');
                    }

                    if ($materielTypeInfo['delete_flag']) {
                        throw new Exception('商品:' . $materielTypeInfo['materiel_name'] . '已被删除，无法添加到套餐中');
                    }

                    if ($value['num'] <= 0) {
                        return ['code' => 1, 'msg' => '套件内商品数量必须大于0', 'data' => ''];
                    }

                    if (!is_numeric($value['num'])) {
                        return ['code' => 1, 'msg' => '套件内商品数量仅能为数字', 'data' => ''];
                    }

                    if ($value['price'] < 0) {
                        return ['code' => 1, 'msg' => '套件内商品单价必须大于0', 'data' => ''];
                    }

                    if (!is_numeric($value['price'])) {
                        return ['code' => 1, 'msg' => '套件内商品单价仅能为数字', 'data' => ''];
                    }

                    $price += $value['price'] * $value['num'];
                    $sellPrice += $value['selling_price'] * $value['num'];

                    $materielInfo = MaterielTypeModel::where('id', $value['type_id'])->first();

                    if ($materielInfo['is_use_serial']) {
                        $hasSerialMateriel = 1;
                    }
                }

                $totalPrice = 0;
                $isUp = 0;
                $discount = 0;
                $calcRatio = 0;
                if ($priceType) {
                    foreach ($productContent as $val) {
                        $typeInfo = MaterielTypeModel::where('id', $val['type_id'])->first();

                        //是否溢价
                        if ($data['selling_price'] > $price) {
                            $isUp = 1;

                            if ($price == 0) {
                                $discount = 0;
                                $calcRatio = 0;
                            } else {
                                $discount = substr((($data['selling_price'] - $price) / $price), 0, 4);
                                $calcRatio = sprintf('%.2f', ($data['selling_price'] / $price));
                            }

                            $newPrice = ($val['price'] * $discount) + $val['price'];
                        } else {
                            $isUp = 0;
                            if ($sellPrice == 0) {
                                $discount = 0;
                            } else {
                                $discount = substr(($price / $sellPrice), 0, 4);
                            }

                            $newPrice = $val['price'] * $discount;

                            if ($price == 0) {
                                $calcRatio = 0;
                            } else {
                                $calcRatio = sprintf('%.2f', ($sellPrice / $price));
                            }
                        }

                        $arr[] = [
                            'main_id' => $data['main_id'],
                            'type_id' => $val['type_id'],
                            'price' => sprintf('%.6f', $newPrice),
                            'origin_price' => $val['selling_price'],
                            'is_use_serial' => $typeInfo['is_use_serial'],
                            'total_price' => sprintf('%.6f', ($newPrice * $val['num'])),
                            'product_id' => $materielTypeId,
                            'num' => $val['num'],
                            'created_at' => $data['created_at']
                        ];

                        $totalPrice += sprintf('%.6f', ($newPrice * $val['num']));
                    }

                    MaterielsTypeModel::where('id', $materielTypeId)
                        ->update([
                            'selling_price' => $data['selling_price'],
                            'ratio' => $discount,
                            'price_up_or_down' => $isUp,
                            'calc_ratio' => $calcRatio,
                        ]);
                } else {
                    foreach ($productContent as $val) {
                        $typeInfo = MaterielTypeModel::where('id', $val['type_id'])->first();

                        $arr[] = [
                            'main_id' => $data['main_id'],
                            'type_id' => $val['type_id'],
                            'price' => sprintf('%.6f', $val['price']),
                            'total_price' => sprintf('%.6f', ($val['price'] * $val['num'])),
                            'origin_price' => $val['selling_price'],
                            'is_use_serial' => $typeInfo['is_use_serial'],
                            'product_id' => $materielTypeId,
                            'num' => $val['num'],
                            'created_at' => $data['created_at']
                        ];

                        $totalPrice += sprintf('%.6f', ($val['price'] * $val['num']));
                    }

                    MaterielsTypeModel::where('id', $materielTypeId)
                        ->update(['selling_price' => $price]);
                }

                MaterielProductContentModel::insert($arr);

                if ($priceType) {
                    $balance = $data['selling_price'] - $totalPrice;

                    $firstData = MaterielProductContentModel::where('product_id', $materielTypeId)
                        ->first();

                    MaterielProductContentModel::where('id', $firstData['id'])
                        ->update([
                            'price' => DB::raw('price +' . ($balance / 10)),
                            'total_price' => DB::raw('total_price +' . $balance)
                        ]);
                }

                //若套件为存在开启了序列号的商品，则套餐标记为必须开启序列号
                MaterielTypeModel::where('id', $materielTypeId)
                    ->update(['is_use_serial' => $hasSerialMateriel]);
            }

            if ($addType) {
                $data['storage_id'] = $storageId;
                $data['batch_title'] = $batchTitle;
                $data['user_id'] = $userId;
                $data['in_storage_time'] = $inStorageTime;
                $data['in_storage_num'] = $inStorageNum;
                $data['serial_info'] = $serialInfo;
                $data['product_content'] = $productContent;
                $data['shelf_id'] = $shelfId;
                $data['location_id'] = $locationId;
                $data['label_id'] = $labelId;
                $data['label_name'] = $labelName;

                self::createStorageManageInfo(1, $materielTypeId, $data, $time);
            }

            if (!empty($data['animal_info'])) {
                $animalInfo = json_decode($data['animal_info'], true);
                $animalArr['created_at'] = time();
                $animalInfo['main_id'] = $data['main_id'];
                $animalInfo['materiel_type_id'] = $materielTypeId;
                MaterielAnimalInfoModel::query()->insert($animalInfo);
            }

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ['id' => $materielTypeId]];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('添加套件异常:' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    public static function editMateriel(array $data, int $userId)
    {
        unset($data['product_content']);
        unset($data['price_type']);
        unset($data['is_product_materiel']);
        unset($data['serial_info']);
        DB::beginTransaction();
        try {
            //验证商品信息除己身外是否已存在
            $checkMaterielInfo = MaterielTypeService::checkMaterielInfoExceptself($data);

            if (!$checkMaterielInfo) {
                return ['code' => 1, 'msg' => '物料类型`' . $data['materiel_name'] . '-' . $data['type_name'] . '`已存在', 'data' => ''];
            }
            $materielTypeInfo = MaterielsTypeModel::where('id', $data['id'])->first();
            $imageArr = [];
            $masterImgArr = [];
            if (!empty($materielTypeInfo['materiel_img']) || !empty($materielTypeInfo['materiel_img_group'])) {
                $masterImgArr = $materielTypeInfo['materiel_img'] . ',' . $materielTypeInfo['materiel_img_group'];
                $masterImgArr = array_unique(explode(',', $masterImgArr));
            }
            if (isset($data['materiel_img'])) {
                if (!empty($data['materiel_img'])) {
                    $data['materiel_img'] = $data['materiel_img'];
                    $data['materiel_img_group'] = $data['materiel_img'];
                    $imageArr[] = $data['materiel_img'];
                    if (strpos($data['materiel_img'], ',') !== false) {
                        $imageArr = explode(',', $data['materiel_img']);
                        $data['materiel_img'] = $imageArr[0];
                    }
                    $delGoodsImgArr = array_diff($masterImgArr, $imageArr);
                } else {
                    $data['materiel_img'] = '';
                    $data['materiel_img_group'] = '';
                    $delGoodsImgArr = [];
                    foreach ($masterImgArr as $mVal) {
                        if (!empty($mVal)) {
                            $delGoodsImgArr[] = $mVal;
                        }
                    }
                }

                if (!empty($delGoodsImgArr) && !empty($masterImgArr)) {
                    foreach ($delGoodsImgArr as $dVal) {
                        $client = new OssClient(
                            config('app.aliyun_oss_key'),
                            config('app.aliyun_oss_secret'),
                            config('app.aliyun_oss_endpoint')
                        );
                        $substrUrl = explode('uploads', $dVal);
                        if (!empty($dVal)) {
                            $client->deleteObject(config('app.aliyun_oss_bucket'), 'uploads' . $substrUrl[1]);
                        }
                    }
                }
            }
            $goodsData = $data;
            unset($goodsData['animal_info']);
            MaterielsTypeModel::where('id', $data['id'])->update($goodsData);
            $storageManageInfo = StorageManageModel::where('type_id', $data['id'])->where('delete_flag', 0)->first();
            if (!empty($storageManageInfo)) {
                StorageManageModel::where([
                    'type_id' => $data['id'],
                    'delete_flag' => 0
                ])->update([
                    'materiel_name' => $data['materiel_name'],
                    'type_name' => $data['type_name'],
                    'materiel_mean_cost' => $data['cost'],
                    'materiel_no' => $data['materiel_no'],
                ]);
            }

            if (isset($data['animal_info'])) {
                $animalArr = json_decode($data['animal_info'], true);

                $animalInfo = MaterielAnimalInfoModel::query()->where(['materiel_type_id' => $data['id']])->first();
                if (!empty($animalInfo)) {
                    MaterielAnimalInfoModel::query()->where(['id' => $animalInfo['id']])->update($animalArr);
                } else {
                    $animalArr['created_at'] = time();
                    $animalArr['main_id'] = $data['main_id'];
                    $animalArr['materiel_type_id'] = $data['id'];
                    MaterielAnimalInfoModel::query()->insert($animalArr);
                }
            }
            CommonService::operateResult($userId, $materielTypeInfo, $data['updated_at']);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('编辑商品信息异常' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    /**
     * 同步修改商品信息
     * @param array $data
     * @param int $userId
     * @return number[]|string[]|number[]|string[]|NULL[]
     */
    public static function syncEditMateriel(array $data, int $userId)
    {
        DB::beginTransaction();
        try {
            $goodsInfo = MaterielsTypeModel::where([
                'id' => $data['id'],
                'main_id' => $data['main_id'],
                'delete_flag' => 0
            ])->first();
            if (empty($goodsInfo)) return fail('', '物料信息不存在');
            $sameNameGoodsList = MaterielsTypeModel::getSameNameGoodsList($goodsInfo);//查询同名称和分类的商品
            if (!empty($sameNameGoodsList)) {
                foreach ($sameNameGoodsList as $gVal) {
                    $classInfo = MaterielClassModel::select(
                        'id',
                        'class_no',
                        'class_name'
                    )->where([
                        'delete_flag' => 0,
                        'is_active' => 1,
                        'main_id' => $data['main_id'],
                        'id' => $data['materiel_class_id'] ?? $goodsInfo['materiel_class_id'],
                    ])->first();
                    if (empty($classInfo)) return fail('', '商品分类不存在');
                    if (isset($data['is_use_serial'])) {
                        if ($gVal['is_use_serial'] != $data['is_use_serial']) {//改变序列号状态，判断商品是否有库存
                            $storageManageInfo = StorageManageModel::where([
                                'type_id' => $gVal['id'],
                                'delete_flag' => 0,
                            ])->where('in_storage_num', '>', 0)->first();
                            if (!empty($storageManageInfo)) {
                                if ($data['is_use_serial'] == 1) {
                                    return fail('', '库存中存在该商品，不能开启序列号，需清空库存');
                                } else {
                                    return fail('', '库存中存在该商品，不能关闭序列号，需清空库存');
                                }
                            }
                        }
                    }
                    if (isset($data['spec_img'])) {
                        $originalSpecImgArr = explode(',', $gVal['spec_img']);
                        if (!empty($data['spec_img']) && !empty($gVal['spec_img'])) {//已经存在和新的图片路径
                            $requestSpecImgArr = explode(',', $data['spec_img']);
                            $collection = collect($originalSpecImgArr);
                            $diff = $collection->diff($requestSpecImgArr);
                            $delSpecImgArr = $diff->all();
                        } elseif (empty($data['spec_img']) && !empty($gVal['spec_img'])) {
                            $delSpecImgArr = $originalSpecImgArr;
                        }

                        if (!empty($delSpecImgArr)) {//如果修改了商品详情，删除oss商品详情图片

                            foreach ($delSpecImgArr as $dVal) {
                                $client = new OssClient(
                                    config('app.aliyun_oss_key'),
                                    config('app.aliyun_oss_secret'),
                                    config('app.aliyun_oss_endpoint')
                                );
                                $substrUrl = explode('uploads', $dVal);
                                $client->deleteObject(config('app.aliyun_oss_bucket'), 'uploads' . $substrUrl[1]);
                            }
                        }
                    }
                    $updData = $data;
                    unset($updData['id']);
                    unset($updData['user_id']);
                    unset($updData['upd_flag']);
                    MaterielsTypeModel::where('id', $gVal['id'])->update($updData);
                    if ($data['upd_flag'] == 1) {
                        StorageManageModel::where([
                            'type_id' => $gVal['id'],
                            'delete_flag' => 0
                        ])
                            ->update([
                                'materiel_name' => $data['materiel_name'],
                                'materiel_class_id' => $classInfo['id'],
                                'materiel_class_name' => $classInfo['class_name'],
                                'materiel_class_no' => $classInfo['class_no']
                            ]);
                    }
                    unset($updData);
                    CommonService::operateResult($data['user_id'], $gVal, $data['updated_at']);
                }
                DB::commit();
                return success();
            }
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('编辑商品信息异常' . var_export($e->getMessage(), true));
            return fail('', $e->getMessage());
        }
    }

    public static function editProductMateriel(array $data, int $userId)
    {
        $newData = $data;
        unset($newData['product_content']);

        $priceType = $data['price_type'];
        unset($data['price_type']);

        $productContent = json_decode($data['product_content'], true);

        $info = MaterielTypeModel::where('id', $data['id'])->first();

        if ($info['product_use_tag']) {
            return ['code' => 1, 'msg' => '目标套餐商品已被使用，无法进行编辑', 'data' => ''];
        }

        self::editMateriel($newData, $userId);
        if ($info['product_use_tag']) {
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } else {
            try {
                MaterielProductContentModel::where('product_id', $data['id'])->delete();

                $sellPrice = 0;
                $price = 0;
                $arr = [];
                foreach ($productContent as $value) {
                    if (!isset($value['type_id']) || empty($value['type_id'])) {
                        return ['code' => 1, 'msg' => '请选择要添加的商品', 'data' => ''];
                    }

                    if ($value['num'] <= 0) {
                        return ['code' => 1, 'msg' => '套件内商品数量必须大于0', 'data' => ''];
                    }

                    if (!is_numeric($value['num'])) {
                        return ['code' => 1, 'msg' => '套件内商品数量仅能为数字', 'data' => ''];
                    }

                    if ($value['price'] < 0) {
                        return ['code' => 1, 'msg' => '套件内商品单价必须大于0', 'data' => ''];
                    }

                    if (!is_numeric($value['price'])) {
                        return ['code' => 1, 'msg' => '套件内商品单价仅能为数字', 'data' => ''];
                    }

                    $sellPrice += $value['selling_price'] * $value['num'];
                    $price += $value['price'] * $value['num'];
                }

                $totalPrice = 0;
                $isUp = 0;
                $discount = 0;
                $calcRatio = 0;
                $hasSerialMateriel = $data['is_use_serial'] ?? 0;
                if ($priceType) {
                    foreach ($productContent as $val) {
                        if ($data['selling_price'] > $price) {
                            $isUp = 1;
                            $discount = substr((($data['selling_price'] - $price) / $price), 0, 4);
                            $newPrice = ($val['price'] * $discount) + $val['price'];
                            $calcRatio = sprintf('%.2f', ($data['selling_price'] / $price));
                        } else {
                            $discount = substr(($price / $sellPrice), 0, 4);
                            $newPrice = $val['price'] * $discount;
                            $calcRatio = $sellPrice / $price;
                            $calcRatio = sprintf('%.2f', $calcRatio);
                        }

                        $typeInfo = MaterielTypeModel::where('id', $val['type_id'])->first();

                        $arr[] = [
                            'main_id' => $data['main_id'],
                            'type_id' => $val['type_id'],
                            'price' => sprintf('%.6f', $newPrice),
                            'origin_price' => ($val['selling_price']),
                            'is_use_serial' => $typeInfo['is_use_serial'],
                            'total_price' => sprintf('%.6f', ($newPrice * $val['num'])),
                            'product_id' => $data['id'],
                            'num' => $val['num'],
                            'created_at' => $data['updated_at']
                        ];

                        $totalPrice += sprintf('%.6f', ($newPrice * $val['num']));

                        if ($typeInfo['is_use_serial']) {
                            $hasSerialMateriel = 1;
                        }
                    }

                    MaterielsTypeModel::where('id', $data['id'])
                        ->update([
                            'selling_price' => $data['selling_price'],
                            'ratio' => $discount,
                            'price_up_or_down' => $isUp,
                            'calc_ratio' => $calcRatio,
                            'is_use_serial' => $hasSerialMateriel
                        ]);
                } else {
                    foreach ($productContent as $val) {
                        $typeInfo = MaterielTypeModel::where('id', $val['type_id'])->first();

                        $arr[] = [
                            'main_id' => $data['main_id'],
                            'type_id' => $val['type_id'],
                            'price' => sprintf('%.6f', $val['price']),
                            'total_price' => sprintf('%.6f', ($val['price'] * $val['num'])),
                            'origin_price' => ($val['selling_price']),
                            'is_use_serial' => $typeInfo['is_use_serial'],
                            'product_id' => $data['id'],
                            'num' => $val['num'],
                            'created_at' => $data['updated_at']
                        ];

                        $totalPrice += sprintf('%.6f', ($val['price'] * $val['num']));

                        if ($typeInfo['is_use_serial']) {
                            $hasSerialMateriel = 1;
                        }
                    }

                    MaterielsTypeModel::where('id', $data['id'])
                        ->update([
                            'selling_price' => $price,
                            'is_use_serial' => $hasSerialMateriel
                        ]);
                }

                MaterielProductContentModel::insert($arr);

                if ($priceType) {
                    $balance = $data['selling_price'] - $totalPrice;

                    $firstData = MaterielProductContentModel::where('product_id', $data['id'])
                        ->first();

                    MaterielProductContentModel::where('id', $firstData['id'])
                        ->update([
                            'price' => DB::raw('price +' . ($balance / 10)),
                            'total_price' => DB::raw('total_price +' . $balance)
                        ]);
                }

                CommonService::operateResult($userId, $productContent, $data['updated_at']);
                DB::commit();
                return ['code' => 0, 'msg' => 'success', 'data' => ''];
            } catch (Exception $e) {
                DB::rollBack();
                Log::debug('编辑套件异常:' . var_export($e->getMessage(), true));
                return ['code' => 1, 'msg' => '编辑套件信息异常', 'data' => ''];
            }
        }
    }

    public static function packageInfo(array $data)
    {
        $materielProductContentInfo = MaterielProductContentModel::select(
            'a.*',
            'materiel_name',
            'type_name',
            'materiel_unit',
            'materiel_img'
        )
            ->where([
                'product_id' => $data['id']
            ])
            ->from('materiel_product_content as a')
            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
            ->get()->toArray();
        if (empty($materielProductContentInfo)) return $materielProductContentInfo;
        if (!empty($data['sell_id'])) {
            $sellInfo = SellGoodsDetailModel::where([
                'sell_id' => $data['sell_id'],
                'materiel_type_id' => $data['id'],
                /* 'is_product_materiel' => 1 */
            ])->first();

            if (empty($sellInfo)) {
                return ['code' => 1, 'msg' => '类型错误，暂无内容', 'data' => ''];
            }

            $price = 0;
            $totalPrice = 0;
            foreach ($materielProductContentInfo as &$value) {
                $value['price'] = $value['price'] * $sellInfo['calc_ratio'];
                $value['total_price'] = $value['total_price'] * $sellInfo['calc_ratio'];

                $price += $value['price'];
                $totalPrice += $value['total_price'];
            }

            if ($sellInfo['price'] > $totalPrice) {//补足
                $balance = $sellInfo['price'] - $totalPrice;

                $materielProductContentInfo[0]['price'] += $balance;
                $materielProductContentInfo[0]['total_price'] += $balance;
            } else {//抵扣
                $balance = $totalPrice - $sellInfo['price'];

                //对套件按价格降序排列
                usort($materielProductContentInfo, function ($a, $b) {
                    if ($a['price'] == $b['price']) {
                        return 0;
                    }

                    return ($a['price'] > $b['price']) ? -1 : 1;
                });

                $materielProductContentInfo[0]['price'] -= $balance;
                $materielProductContentInfo[0]['total_price'] -= $balance;
            }
        }

        foreach ($materielProductContentInfo as &$val) {
            if (!empty($val['materiel_img'])) {
                $materielImg = array_filter(explode(',', $val['materiel_img']), function ($v) {
                    return $v !== '';
                });

                $val['materiel_img'] = $materielImg[0];
            }
        }

        return $materielProductContentInfo;
    }

    public static function updateProductInfo(array $data)
    {
        DB::beginTransaction();

        try {
            if (!$data['is_product_materiel']) {
                //获取目标商品相关的所有套餐信息
                $productContentInfo = MaterielProductContentModel::where('type_id', $data['id'])->get()->toArray();

                if (!empty($productContentInfo)) {
                    //更新目标商品在套餐商品表中的序列号开启状态
                    MaterielProductContentModel::where('type_id', $data['id'])->update(['is_use_serial' => $data['is_use_serial']]);

                    $productId = [];
                    foreach ($productContentInfo as $contentVal) {
                        $productId[] = $contentVal['product_id'];
                    }

                    if (!empty($productId)) {
                        $productId = array_unique($productId);
                        //检查已使用目标商品的套餐是否仍存在使用已开启序列号商品的情况
                        $checkProductInfo = MaterielProductContentModel::where('is_use_serial', 1)
                            ->whereIn('product_id', $productId)->get()->toArray();

                        if (empty($checkProductInfo)) {
                            MaterielTypeModel::where('is_product_materiel', 1)
                                ->whereIn('id', $productId)
                                ->update(['is_use_serial' => 0]);
                        } else {
                            MaterielTypeModel::where('is_product_materiel', 1)
                                ->whereIn('id', $productId)
                                ->update(['is_use_serial' => 1]);
                        }
                    }
                }
            }

            DB::commit();
            return true;
        } catch (Exception $e) {
            DB::rollBack();
            return ['code' => 1, 'msg' => '编辑商品信息失败，请重试', 'data' => ''];
        }
    }

    public static function goodsInfo($data)
    {
        return MaterielTypeModel::where(['id' => $data['id'], 'delete_flag' => 0])->first();
    }

    //新建商品侧入库公共方法
    private static function createStorageManageInfo($type, $materielTypeId, $data, $time)
    {
        $data['in_storage_num'] = $data['in_storage_num'] ?? 0;

        if ($data['in_storage_num'] < 0) {
            throw new Exception('入库数量必须大于等于0');
        }

        $storageInfo = StorageModel::getStorageDetail($data['storage_id']);

        if (empty($storageInfo)) {
            throw new Exception('入库的目标仓库不存在，无法完成入库,请检查后重试');
        }

        $result = self::goodsInStorage($materielTypeId, $data, $time);

//        switch($type) {
//            case 0://新建商品入库
//                $result = self::goodsInStorage($materielTypeId, $data, $time);
//                break;
//            case 1://新建套餐入库
//                $result = self::productInStorage($materielTypeId, $data, $time);
//                break;
//        }

        return $result;
    }

    //新建套餐侧入库
    private static function productInStorage($materielTypeId, $data, $time)
    {
        $productContent = $data['product_content'];

        $storageManageInfo = self::materielAddInStorage($materielTypeId, $data, $time, 1);

        if (!empty($productContent)) {
            //逻辑处理开始
            $serialInfo = '';
            $serialArr = [];
            $getInstorageNum = [];
            foreach ($productContent as $value) {
                //获取套餐内组件商品所需总数
                $productContentNum = $data['in_storage_num'] * $value['num'];

                //获取组件商品信息
                $materielTypeInfo = MaterielsTypeModel::getMaterielInfo($value['type_id']);

                //商品是否开启序列号;0:否;1:是;
                if ($materielTypeInfo['is_use_serial']) {
                    //序列号未填写
//                    if(empty($value['serial_info'])) {
//                        throw new Exception('组件商品:'.
//                            $materielTypeInfo['materiel_name'].'已开启序列号，请填写后重试');
//                    }

                    $serialInfo .= $value['serial_info'] . ',';

                    $serialData = array_unique(array_filter(explode(',', $data['serial_info']), function ($v) {
                        return $v !== '';
                    }));

                    if (!is_integer(count($serialData) / $value['num'])) {
                        throw new Exception('组件商品:' . $materielTypeInfo['materiel_name'] . '填写的序列号与实际入库数量不匹配');
                    }

                    $getInstorageNum[] = count($serialData) / $value['num'];

                    foreach ($serialData as $val) {
                        //检查组件商品序列号信息
                        $checkSerialInfo = SerialNumberModel::where([
                            'serial_no' => $val,
                            'goods_id' => $value['type_id'],
                            'main_id' => $data['main_id'],
                            'delete_flag' => 0
                        ])->first();

                        if (!empty($checkSerialInfo)) {
                            throw new Exception('组件商品:' . $materielTypeInfo['materiel_name'] . '的序列号:' . $val . '已存在，无法重复添加');
                        }

                        //组装序列号数据
                        $serialArr[] = [
                            'storage_manage_id' => 0,
                            'package_storage_id' => $storageManageInfo['storage_manage_id'],
                            'batch_no' => $storageManageInfo['batch_no'],
                            'goods_id' => $value['type_id'],
                            'serial_no' => $val,
                            'package_id' => $materielTypeId,
                            'status' => 1,
                            'created_at' => $time,
                            'main_id' => $data['main_id']
                        ];
                    }
                }
            }

            if (!empty($getInstorageNum)) {
                if (count(array_unique($getInstorageNum)) > 1) {
                    throw new Exception('部分商品之间存在序列号数量和实际入库所需数量不匹配的情况，请检查后重新添加');
                }

                if ($getInstorageNum[0] != $data['in_storage_num']) {
                    throw new Exception('部分商品添加的序列号数量与实际入库所需数量不匹配，请检查后重新添加');
                }
            }

            //插入序列号
            if (!empty($serialArr)) {
                SerialNumberModel::insert($serialArr);
            }

            //将被插入的序列号更新到入库记录中
            LogInStorageModel::where('id', $storageManageInfo['log_id'])->update(['serial_number' => substr($serialInfo, 0, -1)]);
        }

        return true;
    }

    //新建商品侧入库
    private static function goodsInStorage($materielTypeId, $data, $time): bool
    {
        $storageManageInfo = self::materielAddInStorage($materielTypeId, $data, $time, 0);

        $serialArr = [];
        $serialStr = '';

        if ($data['is_use_serial']) {
            if (empty($data['serial_info'])) {
                throw new Exception('商品:' .
                    $data['materiel_name'] . '已开启序列号，请填写后重试');
            }

            $serialStr = $data['serial_info'];

            $serialData = array_unique(array_filter(explode(',', $data['serial_info']), function ($v) {
                return $v !== '';
            }));

            //序列号数量少于商品数量
            if (count($serialData) < $data['in_storage_num']) {
                throw new Exception('组件商品:' .
                    $data['materiel_name'] . '所需序列号数量X' . $data['in_storage_num'] .
                    ',尚缺少X' . ($data['in_storage_num'] - count($serialData)));
            }

            //序列号数量超出商品数量
            if (count($serialData) > $data['in_storage_num']) {
                throw new Exception('组件商品:' .
                    $data['materiel_name'] . '所需序列号数量X' . $data['in_storage_num'] .
                    ',超出X' . (count($serialData) - $data['in_storage_num']));
            }

            foreach ($serialData as $val) {
                //组装序列号数据
                $serialArr[] = [
                    'storage_manage_id' => $storageManageInfo['storage_manage_id'],
                    'package_storage_id' => 0,
                    'batch_no' => $storageManageInfo['batch_no'],
                    'serial_no' => $val,
                    'goods_id' => $materielTypeId,
                    'package_id' => 0,
                    'status' => 1,
                    'main_id' => $data['main_id'],
                    'created_at' => $time
                ];
            }
        }

        if ($serialStr != '') {
            LogInStorageModel::query()
                ->where('id', $storageManageInfo['log_id'])
                ->update(['serial_number' => $serialData]);
        }

        if (!empty($serialArr)) {
            SerialNumberModel::insert($serialArr);
        }

        return true;
    }

    //新建商品公共入库
    private static function materielAddInStorage($materielTypeId, $data, $time, $isProductMateriel = 0): array
    {
        //获取仓库信息
        $storageInfo = StorageModel::where(['id' => $data['storage_id']])->first();

        if (empty($data['location_id'])) {
            //获取货架信息
            $shelfInfo = StorageShelfModel::where([
                'storage_id' => $data['storage_id'],
                'shelf_type' => 1
            ])->first();

            //获取库位信息
            $locationInfo = StorageShelfLocationModel::where([
                'main_id' => $data['main_id'],
                'shelf_id' => $shelfInfo['id'],
                'location_type' => 1
            ])->first();

            $data['location_id'] = $locationInfo['id'];
            $data['shelf_id'] = $shelfInfo['id'];
        }

        //商品信息
        $classInfo = MaterielClassModel::where(['id' => $data['materiel_class_id']])->first();

        //入库商品信息
        $inStorageManageInfo = [
            'materiel_class_id' => $data['materiel_class_id'],//物料二级分类id
            'materiel_class_name' => $classInfo['class_name'],//物料二级分类名称
            'materiel_class_no' => $classInfo['class_no'],//物料二级分类名称
            'type_id' => $materielTypeId,//物料id
            'materiel_name' => $data['materiel_name'],//物料名称
            'type_name' => $data['type_name'],//物料型号名称
            'materiel_no' => $data['materiel_no'],//物料编号
            'materiel_mean_cost' => $data['cost'],
            'storage_id' => $data['storage_id'],//仓库id
            'storage_name' => $storageInfo['storage_name'],//仓库名
            'storage_address' => $storageInfo['storage_address'],//仓库地址
            'is_product_materiel' => $isProductMateriel,
            'in_storage_num' => $data['in_storage_num'],//入库数量
            //'virtual_storage_num' => $data['in_storage_num'],
            'main_id' => $data['main_id'],//主账号id
            'in_storage_time' => $time,//入库时间
            'alert_num' => 0,
            'created_at' => $time,
            'shelf_id' => $data['shelf_id'],
            'location_id' => $data['location_id']
        ];
        $manageInfo = StorageManageModel::query()->where([
            'type_id' => $materielTypeId,
            'delete_flag' => 0,
            'storage_id' => $data['storage_id'],
            'shelf_id' => $data['shelf_id'],
            'location_id' => $data['location_id']
        ])->first();
        if (!empty($manageInfo)) {
            $manageInfo->in_storage_num += $data['in_storage_num'];
            $manageInfo->materiel_mean_cost = $data['cost'];
            $manageInfo->save();
            $storageManageId = $manageInfo['id'];
        } else {
            $storageManageId = StorageManageModel::insertGetId($inStorageManageInfo);
        }

        //批次号生成
        $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
        $checkBatchNo = StorageBatchModel::where('main_id', $data['main_id'])
            ->where('batch_no', $batchNo)->first();

        do {
            $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
        } while (!empty($checkBatchNo));

        $batchId = MaterielService::createBatchInfoGetId(
            $batchNo,
            $storageManageId,
            $data['cost'],
            $data['in_storage_num'],
            0,
            $data['main_id']
        );

        //入库日志信息
        $logData = [
            'curr_storage_manage_id' => $storageManageId,
            'materiel_type_id' => $materielTypeId,//物料id
            'batch_id' => $batchId,//物料id
            'materiel_name' => $data['materiel_name'],//物料名称
            'type_name' => $data['type_name'],//物料型号
            'materiel_no' => $data['materiel_no'],//物料编号
            'materiel_class_id' => $data['materiel_class_id'],//物料二级分类主键名称
            'materiel_class_name' => $classInfo['class_name'],//物料二级分类名称
            'materiel_class_no' => $classInfo['class_no'],//物料二级分类编号
            'type' => 2,//入库日志类型;0:入库;1:调拨入库;2:直接入库;
            'storage_id' => $data['storage_id'],//仓库主键id
            'storage_name' => $storageInfo['storage_name'],//仓库名
            'storage_address' => $storageInfo['storage_address'],//仓库地址
            'last_storage_id' => 0,//调拨前所在仓库id
            'operate_num' => $data['in_storage_num'],//操作数量
            'last_storage_num' => 0,//操作前库存数
            'materiel_mean_cost' => $data['cost'],//物料均价
            'next_storage_num' => $data['in_storage_num'],//操作后库存数
            'all_id_type' => 0,//单据类型;0:无;1:报溢;2:退货;3:采购;
            'in_storage_time' => $time,//入库时间
            'shelf_id' => $data['shelf_id'],
            'location_id' => $data['location_id'],
            'all_id' => 0,//单据id
            'user_id' => $data['user_id'],//操作人用户id
            'main_id' => $data['main_id'],//主账号id
            'remark' => empty($data['remark']) ? '' : $data['remark'],
            'label_id' => $data['label_id'],
            'label_name' => $data['label_name'],
            'created_at' => $time,
        ];

        $logId = LogInstorageModel::query()->insertGetId($logData);
//        MessageService::sendInSms(
//            time(),
//            $data['materiel_name'],
//            $data['type_name'],
//            $data['storage_id'],
//            $storageInfo['storage_name'],
//            $data,
//            $data['in_storage_num'],
//            $data['in_storage_num']
//        );

        return ['storage_manage_id' => $storageManageId, 'log_id' => $logId, 'batch_no' => $batchNo];
    }

    /**
     * 处理商品规格数据方法(ADD AND EDIT)
     * @param unknown $data
     * @param unknown $goodsArray
     * @param unknown $time
     * @return \Illuminate\Http\JsonResponse|unknown
     */
    public static function handleGoodsSpceInfo($data, $time, $isUseShelf, $goodsInfo = [], $method = 'add')
    {
        $goodsArr = json_decode($data['goods_spce_info'], true);
        $flag = $data['is_product_materiel'] == 1 ? '套餐' : '商品';
        if (!is_array($goodsArr)) {
            return fail('', $flag . '规格数据集异常！');

        } elseif (count($goodsArr) == 0) {
            $goodsArr[0]['type_name'] = "";
            $goodsArr[0]['materiel_no'] = "";
            /*if ($method == 'edit') {*/
            $goodsArr[0]['selling_price'] = "";
            $goodsArr[0]['lower_selling_price'] = "";
            $goodsArr[0]['cost'] = "";
            /*}*/
        }

        $barCodeArr = array_column($goodsArr, 'bar_code');
        // 使用array_filter去除空值和空字符串
        $filteredArray = array_filter($barCodeArr, function ($value) {
            return ($value !== null && $value !== '');
        });
        //重置数组键名
        $barCodeArr = array_values($filteredArray);
        if (!empty($barCodeArr)) {
            $uniqueBarCodeArr = array_unique($barCodeArr);
            if (count($barCodeArr) != count($uniqueBarCodeArr)) {
                return fail('', '条形码，不允许重复!');
            }
        }
        unset($data['goods_spce_info']);
        foreach ($goodsArr as &$gVal) {//验证商品数据
            if (!empty($gVal['selling_price']) && $gVal['selling_price'] < 0) {
                return fail('', '物料`' . $data['materiel_name'] . '-' . $gVal['type_name'] . '销售价格不能小于0元');
            } else {

            }
            if (!empty($gVal['lower_selling_price']) && $gVal['lower_selling_price'] < 0) {
                return fail('', '物料`' . $data['materiel_name'] . '-' . $gVal['type_name'] . '最低销售价格不能小于0元');
            }
            if (!empty($gVal['cost']) && $gVal['cost'] < 0) {
                return fail('', '物料`' . $data['materiel_name'] . '-' . $gVal['type_name'] . '成本不能小于0元');
            }
            if ($method === 'edit') {//修改
                if ($goodsInfo['selling_price'] != $gVal['selling_price']) {
                    if ($goodsInfo['price_num'] == 0) {
                        $data['price_one'] = $gVal['selling_price'];
                        $data['price_num'] = 1;
                    } elseif ($goodsInfo['price_num'] == 1) {
                        $data['price_two'] = $gVal['selling_price'];
                        $data['price_num'] = 2;
                    } elseif ($goodsInfo['price_num'] == 2) {
                        $data['price_three'] = $gVal['selling_price'];
                        $data['price_num'] = 3;
                    } elseif ($goodsInfo['price_num'] == 3) {
                        $data['price_four'] = $gVal['selling_price'];
                        $data['price_num'] = 4;
                    } elseif ($goodsInfo['price_num'] == 4) {
                        $data['price_five'] = $gVal['selling_price'];
                        $data['price_num'] = 0;
                    }
                }
            }
            $goodsData = array_merge($data, $gVal);
            if (!empty($goodsData['bar_code'])) {//检查条形码是否存在
                $GoodsCodeInfo = MaterielTypeModel::where([
                    'main_id' => $data['main_id'],
                    'bar_code' => $goodsData['bar_code'],
                    'delete_flag' => 0,
                ]);
                if ($method === 'edit')
                    $GoodsCodeInfo->where('id', '!=', $goodsInfo['id']);
                $materielTypeInfo = $GoodsCodeInfo->first();
                if (!empty($materielTypeInfo)) {
                    return fail('', '条形码' . $goodsData['bar_code'] . '`已存在!');
                }
            } else {
                if ($method === 'add') {
                    $year = substr(Carbon::parse()->year, -2);
                    $orderNo = $year . mt_rand(100000000, 999999999);
                    do {
                        $orderNo = $year . mt_rand(100000000, 999999999);
                    } while (!empty(MaterielTypeModel::query()->where('bar_code', $orderNo)->exists()));
                    $goodsData['bar_code'] = $orderNo;
                }
            }
            if (!empty($goodsData['inventory_code'])) {//检查库存码是否存在
                $GoodsCodeInfo = MaterielTypeModel::where([
                    'main_id' => $data['main_id'],
                    'inventory_code' => $goodsData['inventory_code'],
                    'delete_flag' => 0,
                ]);
                if ($method === 'edit')
                    $GoodsCodeInfo->where('id', '!=', $goodsInfo['id']);
                $materielTypeInfo = $GoodsCodeInfo->first();
                if (!empty($materielTypeInfo)) {
                    return fail('', '库存码' . $goodsData['inventory_code'] . '`已存在!');
                }
            }
            if (!empty($data['number_prefix'])) {
                $GoodsPrefixInfo = MaterielTypeModel::where([
                    'main_id' => $data['main_id'],
                    'number_prefix' => $data['number_prefix'],
                    'delete_flag' => 0
                ]);
                if ($method === 'edit')
                    $GoodsPrefixInfo->where('id', '!=', $goodsInfo['id']);
                $materielTypeInfo = $GoodsPrefixInfo->first();

                if (!empty($materielTypeInfo)) {
                    return fail('', '物料`' . $materielTypeInfo['materiel_name'] . '的编号前缀' . $goodsData['number_prefix'] . '`已存在!');
                }
            }
            //验证商品信息是否已存在
            $checkMaterielInfo = MaterielTypeModel::query()
                ->select(
                    'id',
                    'materiel_name'
                )->where([
                    'materiel_name' => $goodsData['materiel_name'],
                    'main_id' => $goodsData['main_id'],
                    'materiel_class_id' => $goodsData['materiel_class_id'],
                    'delete_flag' => 0,
                    'type_name' => $goodsData['type_name'],
                    'materiel_no' => $goodsInfo['materiel_no'] ?? $goodsData['materiel_no']
                ]);

            if ($method === 'edit') {
                $checkMaterielInfo->where([
                    ['id', '!=', $goodsInfo['id']],
                ]);
            }
            $checkMaterielInfo = $checkMaterielInfo->first();
            if (!empty($checkMaterielInfo) && $method === 'add') {
                if (empty($data['is_cover'])) {
                    if ($data['is_product_materiel']) {
                        return fail('', '套餐名称`' . $data['materiel_name'] . '`已存在');
                    }
                    return response()->json(['code' => 0,
                        'data' =>
                            ['code' => 66,
                                'msg' => '商品名称`' . $goodsData['materiel_name'] . '-' . $goodsData['type_name'] . '`已存在！相同属性商品信息，是否选择更新（商品库存会进行叠加）']
                    ]);
                }
            } elseif (!empty($checkMaterielInfo) && $method === 'edit') {
                return fail('', '商品名称`' . $data['materiel_name'] . '`已存在');
            }
            unset($goodsData);
        }
        $idArr = [];
        foreach ($goodsArr as $oVal) {//添加商品数据
            $goodsData = array_merge($data, $oVal);
            if ($data['is_product_materiel']) {//创建套件
                unset($goodsData['is_cover']);
                if ($method == 'edit') {//修改
                    unset($goodsData['user_id']);
                    $result = MaterielTypeService::editProductMateriel($goodsData, $data['user_id']);
                } else {//新加
                    $result = MaterielTypeService::addProductMateriel($goodsData, $time, $isUseShelf);
                }
            } else {//创建商品
                if ($method == 'edit') {//修改
                    unset($goodsData['user_id']);
                    $result = MaterielTypeService::editMateriel($goodsData, $data['user_id']);
                    MaterielTypeService::updateProductInfo($goodsData);
                } else {//新加
                    if (!empty($data['is_cover'])) {
                        $checkMaterielInfo = MaterielTypeModel::query()
                            ->select(
                                'id',
                                'materiel_name'
                            )->where([
                                'materiel_name' => $goodsData['materiel_name'],
                                'main_id' => $goodsData['main_id'],
                                'materiel_class_id' => $goodsData['materiel_class_id'],
                                'delete_flag' => 0,
                                'type_name' => $goodsData['type_name'],
                                'materiel_no' => $goodsData['materiel_no']
                            ])->first();
                        if (empty($checkMaterielInfo)) {
                            unset($goodsData['is_cover']);
                            $result = MaterielTypeService::add($goodsData, $time, $isUseShelf);
                        } else {
                            //覆盖相同名称商品信息
                            $goodsData['id'] = $checkMaterielInfo['id'];
                            $result = SELF::editTheSameMateriel($goodsData, $data['user_id'], $time);
                        }
                    } else {

                        $result = MaterielTypeService::add($goodsData, $time, $isUseShelf);
                    }
                }
            }

            if (!empty($result['code'])) {
                return fail('', $result['msg']);
            } else {
                if (!empty($result['data']['id'])) {
                    $idArr[] = $result['data']['id'];
                } elseif (!empty($data['is_cover'])) {
                    $idArr[] = $goodsData['id'];
                }
            }
            unset($goodsData);
            if ($method == 'edit') return success();
        }
        CommonService::operateResult($data['user_id'], $time, $result);
        return success(['ids' => $idArr]);
    }

    /**
     * 同规格商品列表
     * @param unknown $id
     * @return array
     */
    static public function sameNameGoodsList($data)
    {
        $info = MaterielTypeModel::getInfo($data['id']);
        if (!empty($info)) {
            if (!empty($info['is_product_materiel']))
                return fail('', '套餐未开启查询同规格商品功能');
            $goodsList = MaterielTypeModel::getSanmeGoodsList($info, $data['pageSize'], $data['currentPage']);
            if (!empty($goodsList['data'])) {
                foreach ($goodsList['data'] as &$gVal) {
                    $info['spec_img'] = !empty($gVal['spec_img']) ? explode(',', $gVal['spec_img']) : [];
                    $info['materiel_img_group'] = !empty($gVal['materiel_img_group']) ? explode(',', $gVal['materiel_img_group']) : [];
                    $info['materiel_img'] = $gVal['materiel_img'] ?? '';
                }
            }
            return success($goodsList);
        } else {
            return fail('', '没有商品信息');
        }
    }

    /**
     * 商品图片列表
     * @param Request $request
     */
    static public function getImagesList($data)
    {
        if ($data['currentPage'] == 1) {
            set_time_limit(300);
            if (empty(cache::get('img_list'))) {
                $list = Cache::remember('img_list', 10, function () use ($data) {
                    return MaterielTypeModel::getImagesList($data);
                });
                foreach ($list as $val) {
                    if (strpos($val['materiel_img'], ',') !== false) {
                        $arr = array_unique(array_filter(
                            explode(',', $val['materiel_img']),
                            function ($v) {
                                return $v !== '';
                            }));
                        foreach ($arr as $iVal) {
                            AuditImagesModel::insert([
                                'goods_id' => $val['id'],
                                'main_id' => $val['main_id'],
                                'username' => $val['username'],
                                'goods_img' => $iVal,
                                'goods_name' => $val['materiel_name'],
                                'goods_no' => $val['materiel_no'],
                                'created_at' => Carbon::now()->timestamp
                            ]);
                        }
                    } else {
                        AuditImagesModel::insert([
                            'goods_id' => $val['id'],
                            'main_id' => $val['main_id'],
                            'username' => $val['username'],
                            'goods_img' => $val['materiel_img'],
                            'goods_name' => $val['materiel_name'],
                            'goods_no' => $val['materiel_no'],
                            'created_at' => Carbon::now()->timestamp
                        ]);
                    }
                }
            }
        }
        if (!empty($data['start_time'])) {
            $startTimeArr = explode(' ', $data['start_time']);
            $startTime = strtotime($startTimeArr[0] . ' 00:00:00');
        }
        if (!empty($data['end_time'])) {
            $endTimeArr = explode(' ', $data['end_time']);
            $endTime = strtotime($endTimeArr[0] . ' 23:59:59');
        }
        $query = AuditImagesModel::where([
            'check_flag' => 0,
            'delete_flag' => 0
        ]);
        if (!empty($startTime) && !empty($endTime)) {
            $query->whereBetween('created_at', [$startTime, $endTime]);
        } else if (!empty($startTime) && empty($endTime)) {
            $query->where('created_at', '>=', $startTime);
        } else if (empty($startTime) && !empty($endTime)) {
            $query->where('created_at', '<=', $endTime);
        }
        return $query->distinct()
            ->orderBy('id', 'DESC')
            ->paginate($data['pageSize'], ['*'], '', $data['currentPage'])->toArray();
    }

    /**
     * 生成物料第一张图片的缩略图，以方便excel 导出使用
     * @return void
     */
    static public function materielTypeImgResize($downloadFile)
    {
        if ($downloadFile == '') {
            return false;
        }

        //如果已经存在就不用再去抓取了
        $imgPath = $downloadFile;//图片路径
        if (file_exists(public_path() . $imgPath)) {
            return false;
        }

        $imgPathArr = explode('/', $downloadFile);

        if (count($imgPathArr) >= 5) {
            unset($imgPathArr[0], $imgPathArr[1]);
        } else {
            return false;
        }

        $imgPath = implode('/', $imgPathArr);
        $ossObject = substr($downloadFile, 1);

        $imgOssUrlResize = config('app.sm_img_url') . $downloadFile . '?x-oss-process=image/resize,m_fill,w_80,h_80';

        //先判断oss上是否存在try{
        try {

            $ossClient = new OssClient(
                config('app.aliyun_oss_key'),
                config('app.aliyun_oss_secret'),
                config('app.aliyun_oss_endpoint'),
            );

            $exist = $ossClient->doesObjectExist(config('app.aliyun_oss_bucket'), $ossObject);

            if ($exist) {
                $sourceImg = file_get_contents($imgOssUrlResize);
                if ($sourceImg != false) {
                    Storage::put($imgPath, $sourceImg);//存储图片
                }
            }

        } catch (OssException $e) {

            //printf(__FUNCTION__ . ": FAILED\n");
            //printf($e->getMessage() . "\n");
            return false;
        }

        return true;
    }

    public static function getGoodsDetail($data)
    {
        $info = MaterielTypeModel::query()
            ->select(
                'b.id',
                'b.materiel_name',
                'b.type_name',
                'c.class_name as secClassName',
                'd.class_name as firClassName',
                'b.materiel_no',
                'b.number_prefix',
                'b.is_product_materiel',
                'b.materiel_img',
                'b.spec_img',
                'b.materiel_unit',
                'b.selling_price',
                'b.length',
                'b.width',
                'b.weight',
                'b.width',
                'height',
                'b.cost',
                'executive_standard',
                'texture',
                'b.bar_code',
                'b.inventory_code'
            )->from('materiel_type as b')
            ->leftJoin('materiel_class as c', 'c.id', '=', 'b.materiel_class_id')
            ->leftJoin('materiel_class as d', 'd.id', '=', 'c.parent_id')
            ->where([
                'b.id' => $data['goods_id'],
                'b.delete_flag' => 0,
            ])->first();
        if (empty($info)) return '';
        // 生成PNG格式的条形码并保存到服务器
        if (!empty($info['bar_code'])) {
            $DNS1D = new DNS1D();
            $resl = $DNS1D->getBarcodePNG($info['bar_code'], 'C128A');
            $info['bar_code_img'] = $resl ?? "";
        }
        $info['product_content'] = '';
        if ($info['is_product_materiel'] == 1) {
            $info['product_content'] = MaterielProductContentModel::query()
                ->select(
                    'a.price',
                    'a.num',
                    'b.materiel_name'
                )->from('materiel_product_content as a')
                ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
                ->where([
                    'product_id' => $info['id'],
                    'a.delete_flag' => 0
                ])->get();
        }
        $StorageInfo = StorageManageModel::query()
            ->select(
                'id',
                'in_storage_num'
            )->where([
                'type_id' => $info['id'],
                'delete_flag' => 0,
            ])->get();
        if (empty($StorageInfo->toArray())) $info['total_num'] = 0;
        $info['batch_list'] = '';
        $info['serial_list'] = '';
        $info['in_out_list'] = '';
        if (!empty($StorageInfo->toArray())) {
            $totalNum = 0;
            foreach ($StorageInfo->toArray() as $val) {
                $totalNum += $val['in_storage_num'];
                $storageManageIdArr[] = $val['id'];
            }
            $info['total_num'] = $totalNum;
            $batchList = StorageBatchModel::query()
                ->where([
                    'delete_flag' => 0
                ])->whereIn('storage_manage_id', $storageManageIdArr)
                ->pluck('batch_no');
            $serielList = SerialNumberModel::query()
                ->where([
                    'delete_flag' => 0,
                    'goods_id' => $data['goods_id']
                ])->whereIn('storage_manage_id', $storageManageIdArr)
                ->pluck('serial_no');

            $info['serial_list'] = !empty($serielList->toArray()) ? $serielList->toArray() : '';
            $info['batch_list'] = !empty($batchList->toArray()) ? $batchList->toArray() : '';
            $inStorageLogList = LogInStorageModel::query()
                ->select(
                    'b.materiel_name',
                    'b.type_name',
                    'a.created_at',
                    'all_id_type',
                    'operate_num',
                    'nickname'
                )->from('log_instorage as a')
                ->leftJoin('materiel_type as b', 'b.id', '=', 'a.materiel_type_id')
                ->leftJoin('admin as c', 'c.id', '=', 'a.user_id')
                ->where([
                    'a.delete_flag' => 0,
                    'materiel_type_id' => $info['type_id'],
                ])->whereIn('curr_storage_manage_id', $storageManageIdArr)->get();
            if (!empty($inStorageLogList->toArray())) {
                foreach ($inStorageLogList as &$val) {
                    $operateType = '快速入库';
                    switch ($val['all_id_type']) {
                        case 1:
                            $operateType = '报溢入库';
                            break;
                        case 2:
                            $operateType = '退货入库';
                            break;
                        case 3:
                            $operateType = '采购入库';
                            break;
                        case 4:
                            $operateType = '生产还库';
                            break;
                        case 6:
                            $operateType = '组件返仓';
                            break;
                        case 7:
                            $operateType = '导入入库';
                            break;
                        case 8:
                            $operateType = '撤销还库';
                            break;
                        case 9:
                            $operateType = '退换货入库';
                            break;
                        default:
                            $operateType = '快速入库';
                            break;
                    }
                    $val['operate_type'] = $operateType;
                    $val['in_out_type'] = 1;
                }
            }
            $outStorageLogList = LogOutStorageModel::query()
                ->select(
                    'b.materiel_name',
                    'b.type_name',
                    'a.created_at',
                    'all_id_type',
                    'operate_num',
                    'nickname'
                )->from('log_outstorage as a')
                ->leftJoin('materiel_type as b', 'b.id', '=', 'a.materiel_type_id')
                ->leftJoin('admin as c', 'c.id', '=', 'a.user_id')
                ->where([
                    'a.delete_flag' => 0,
                    'materiel_type_id' => $info['id'],
                ])->whereIn('curr_storage_manage_id', $storageManageIdArr)->get();

            if (!empty($outStorageLogList->toArray())) {
                foreach ($outStorageLogList as &$val) {
                    $operateType = '快速出库';
                    switch ($val['all_id_type']) {
                        case 1:
                            $operateType = '报损出库';
                            break;
                        case 2:
                            $operateType = '销售出库';
                            break;
                        case 3:
                            $operateType = '生产出库';
                            break;
                        case 4:
                            $operateType = '导入出库';
                            break;
                        case 5:
                            $operateType = '撤销出库';
                            break;
                        case 6:
                            $operateType = '换货出库';
                            break;
                        case 7:
                            $operateType = '生产损耗出库';
                            break;
                        default:
                            $operateType = '快速出库';
                            break;
                    }
                    $val['in_out_type'] = 2;
                    $val['operate_type'] = $operateType;
                }
            }

            $list = array_merge($inStorageLogList->toArray(), $outStorageLogList->toArray());
            if (!empty($list)) {
                $timeKey = array_column($list, 'created_at');
                array_multisort($timeKey, SORT_DESC, $list);
            }
            $info['in_out_list'] = $list ?? '';
        }
        $info['animal_info'] = MaterielAnimalInfoModel::query()
            ->where([
                'delete_flag' => 0,
                'materiel_type_id' => $info['id']
            ])->first() ?? '';
        return $info;
    }

    public static function editTheSameMateriel(array $data, int $userId, $time)
    {

        $shelfId = $data['shelf_id'] ?? '';
        $locationId = $data['location_id'] ?? '';
        $addType = $data['add_type'] ?? '';
        $storageId = $data['storage_id'] ?? '';
        $batchTitle = $data['batch_title'];
        $labelId = $data['label_id'];
        $inStorageTime = $data['in_storage_time'];
        $inStorageNum = !empty($data['in_storage_num']) ? $data['in_storage_num'] : 0;
        $serialInfo = $data['serial_info'] ?? [];
        $labelName = $data['label_name'];
        unset($data['product_content']);
        unset($data['price_type']);
        unset($data['is_product_materiel']);
        unset($data['serial_info']);
        unset($data['storage_id']);
        unset($data['in_storage_time']);
        unset($data['label_name']);
        unset($data['in_storage_num']);
        unset($data['batch_title']);
        unset($data['user_id']);
        unset($data['add_type']);
        unset($data['shelf_id']);
        unset($data['location_id']);
        unset($data['label_id']);
        DB::beginTransaction();
        try {
            $materielTypeInfo = MaterielsTypeModel::where('id', $data['id'])->first();
            $imageArr = [];
            $masterImgArr = [];
            if (!empty($materielTypeInfo['materiel_img']) || !empty($materielTypeInfo['materiel_img_group'])) {
                $masterImgArr = $materielTypeInfo['materiel_img'] . ',' . $materielTypeInfo['materiel_img_group'];
                $masterImgArr = array_unique(explode(',', $masterImgArr));
            }
            if (isset($data['materiel_img'])) {
                if (!empty($data['materiel_img'])) {
                    $data['materiel_img'] = $data['materiel_img'];
                    $data['materiel_img_group'] = $data['materiel_img'];
                    $imageArr[] = $data['materiel_img'];
                    if (strpos($data['materiel_img'], ',') !== false) {
                        $imageArr = explode(',', $data['materiel_img']);
                        $data['materiel_img'] = $imageArr[0];
                    }
                    $delGoodsImgArr = [];
                    if (!empty($masterImgArr)) {
                        $delGoodsImgArr = array_diff($masterImgArr, $imageArr);
                    }
                } else {
                    $data['materiel_img'] = '';
                    $data['materiel_img_group'] = '';
                    $delGoodsImgArr = [];
                    foreach ($masterImgArr as $mVal) {
                        if (!empty($mVal)) {
                            $delGoodsImgArr[] = $mVal;
                        }
                    }
                }

                if (!empty($delGoodsImgArr) && !empty($masterImgArr)) {
                    foreach ($delGoodsImgArr as $dVal) {
                        $client = new OssClient(
                            config('app.aliyun_oss_key'),
                            config('app.aliyun_oss_secret'),
                            config('app.aliyun_oss_endpoint')
                        );
                        $substrUrl = explode('uploads', $dVal);
                        $client->deleteObject(config('app.aliyun_oss_bucket'), 'uploads' . $substrUrl[1]);
                    }
                }
            }
            $goodsData = $data;
            unset($goodsData['is_cover']);
            unset($goodsData['animal_info']);
            $bool = MaterielsTypeModel::where('id', $data['id'])->update($goodsData);
            $storageManageInfo = StorageManageModel::query()
                ->where([
                    'type_id' => $data['id'],
                    'delete_flag' => 0
                ])->first();
            if (!empty($storageManageInfo)) {
                StorageManageModel::where([
                    'type_id' => $data['id'],
                    'delete_flag' => 0
                ])->update([
                    'materiel_name' => $data['materiel_name'],
                    'type_name' => $data['type_name'],
                    'materiel_mean_cost' => $data['cost'],
                    'materiel_no' => $data['materiel_no'],
                ]);
            }
            if ($addType) {
                $data['storage_id'] = $storageId;
                $data['batch_title'] = $batchTitle;
                $data['user_id'] = $userId;
                $data['in_storage_time'] = $inStorageTime;
                $data['in_storage_num'] = $inStorageNum;
                $data['serial_info'] = $serialInfo;
                $data['shelf_id'] = $shelfId;
                $data['location_id'] = $locationId;
                $data['label_name'] = $labelName;
                $data['label_id'] = $labelId;
                self::createStorageManageInfo(0, $data['id'], $data, $time);
            }
            if (isset($data['animal_info'])) {
                $animalArr = json_decode($data['animal_info'], true);
                $animalInfo = MaterielAnimalInfoModel::query()->where(['materiel_type_id' => $data['id']])->first();
                if (!empty($animalInfo)) {
                    MaterielAnimalInfoModel::query()->where(['id' => $animalInfo['id']])->update($animalArr);
                } else {
                    $animalArr['created_at'] = $time;
                    $animalArr['main_id'] = $data['main_id'];
                    $animalArr['materiel_type_id'] = $data['id'];
                    MaterielAnimalInfoModel::query()->insert($animalArr);
                }
            }
            CommonService::operateResult($userId, $materielTypeInfo, $time);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('编辑商品信息异常' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }
}
